import A3Object from "./A3Object.js";
import A3ObjectTypes from "./A3ObjectTypes.js";
import { A3MonocularCamera } from "./graphics/Graphics.js";
import A3Ground, { A3Ceiling, A3Door, A3Floor, A3Wall } from "./modules/static/A3Ground.js";
import { worldTransform, toAmmoType } from "./physics/AmmoHelper.js";

function newA3Object( data ){
  
  let obj;
  const type = data.type;

  switch ( type ){

    case A3ObjectTypes.A3ObjectGroup: obj = A3ObjectGroup.fromJson( data );break;

    case A3ObjectTypes.Ceiling: obj = A3Ceiling.fromJson( data );break;
    case A3ObjectTypes.Floor: obj = A3Floor.fromJson( data );break;
    case A3ObjectTypes.Wall: obj = A3Wall.fromJson( data );break;
    case A3ObjectTypes.Door: obj = A3Door.fromJson( data );break;
    case A3ObjectTypes.Ground: obj = A3Ground.fromJson( data );break;

    case A3ObjectTypes.MonocularCamera: obj = A3MonocularCamera.fromJson( data );break;

    default: obj = A3Object.fromJson( data );break

  }

  return obj;

}

/**
 * A3对象组
 */
class A3ObjectGroup extends A3Object{

  type=A3ObjectTypes.A3ObjectGroup;
  name=A3ObjectTypes.A3ObjectGroup;

  isA3Object = false;
  isA3ObjectGroup = true;

  children=[];
  childMap = new WeakMap();

  enableBaseShape = false;

  constructor( width, height, depth, meshType="box", constructOnly=false ){
    
    super( width, height, depth, meshType, constructOnly );
    if( constructOnly ) return;

    this.visual.visible = false;
  }

  addChild( child ) {

    // if( this.threeObject ) {
    //   this.threeObject.add( child.threeObject );
    // }

    this.children.push( child );
    this.childMap.set( child, 
      {
        index:this.children.length - 1,
        position: child.position.clone(),
        quaternion: child.quaternion.clone(),
      } );

  }

  removeChild( child ) {

    if( this.childMap.has( child ) ) {
      const index = this.childMap.get( child ).index;
      this.children.splice( index, 1 );
      this.childMap.delete( child );
    }

  }

  // addConstraint( parentIndex, childIndex, )

  updateWorldTransform( position, quaternion ) {

    if( !position ) {
      position = this.position;
    }

    if( !quaternion ) {
      quaternion = this.quaternion;
    }

    if ( this.threeObject ) {

      this.threeObject.position.copy( position );
      this.threeObject.quaternion.copy( quaternion );

    }
 
    if( this.enableBaseShape && this.physicsBody ) {
      
      const ms = this.physicsBody[0].getMotionState();
      ms.getWorldTransform( worldTransform );
      worldTransform.setOrigin( toAmmoType( position ) );
      worldTransform.setRotation( toAmmoType( quaternion ) );
      this.physicsBody[0].setWorldTransform( worldTransform );
      
    }

    this.position.copy( position );
    this.quaternion.copy( quaternion );

    for( var i = 0, il = this.children.length; i < il; i++ ) {
      const childInfo = this.childMap.get( this.children[i] );

      const tmpPos = childInfo.position.clone();
      const quat = childInfo.quaternion.clone();
      const tmpQuat = this.quaternion.clone();

      tmpPos.applyQuaternion( this.quaternion );
      tmpQuat.multiply( quat );    
      tmpPos.add( this.position );

      this.children[i].updateWorldTransform( tmpPos, tmpQuat );
    }

  }

  updateChildTransform( child, position, quaternion ) {
    
    if( this.childMap.has( child ) ) {

      child.updateWorldTransform( position, quaternion );

    }

  }

  toJson() {
    
    const data = super.toJson();

    data["children"] = [];
    for( var i = 0, il = this.children.length; i < il; i++ ) {
      data["children"].push( this.children[i].toJson() );
    }

    return data;

  }

  static fromJson( data, obj, passChild=false ) {
    
    if ( obj === null || obj === undefined ) {
      obj = new A3ObjectGroup( data.width, data.height, data.depth );
    }

    super.fromJson( data, obj );

    if( passChild ) return obj;

    const children = data.children;

    for( var i = 0, il = children.length; i < il; i++ ) {
      const child = newA3Object( children[i] );
      obj.addChild( child );
    }

    return obj;
    
  }

  update(){

    if( this.enableBaseShape ) {
      super.update();
    }

    for( var i = 0, il = this.children.length; i < il; i++ ) {
      this.children[i].update();
    }

  }

  store() {

    if( this.enableBaseShape ){
      super.store();
    }

    for( var i = 0, il = this.children.length; i < il; i++ ) {
      this.children[i].store();
    }

  }

  reset(){

    if( this.enableBaseShape ){
      super.reset();
    }

    for( var i = 0, il = this.children.length; i < il; i++ ) {
      this.children[i].reset();
    }
  }

}

export default A3ObjectGroup;

export {
  newA3Object
}